﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ExtensionHelper
{
    public static partial class ExtensionHelper
    {
        //DebuggerStepThrough指示调试器逐句通过代码，而不是进入并单步执行代码

        #region IEnumerable
        /// <summary>
        /// 转换成大写,集合中延迟执行大写
        /// </summary>
        /// <param name="col"></param>
        /// <returns></returns>
        public static IEnumerable<string> ToUpperCase(this IEnumerable<string> col)
        {
            if (!col.IsEmpty())
            {
                foreach (string s in col)
                {
                    yield return s.ToUpper();
                }
            }
        }
        /// <summary>
        /// 转换成小写,集合中延迟执行小写
        /// </summary>
        /// <param name="col"></param>
        /// <returns></returns>
        public static IEnumerable<string> ToLowerCase(this IEnumerable<string> col)
        {
            if (!col.IsEmpty())
            {
                foreach (string s in col)
                {
                    yield return s.ToLower();
                }
            }
        }
        /// <summary>
        /// 公开枚举器是否为空
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="col"></param>
        /// <returns></returns>
        [DebuggerStepThrough]
        public static bool IsEmpty<T>(this IEnumerable<T> col)
        {
            if (col == null)
                return false;
            else
                return !col.GetEnumerator().MoveNext();
        }

        /// <summary>  
        /// 给非强类型的IEnumerable返回头一个元素。 
        /// </summary>  
        [DebuggerStepThrough]
        public static object First(this IEnumerable col)
        {
            foreach (var item in col)
                return item;
            throw new IndexOutOfRangeException();
        }

        /// <summary>  
        /// 给非强类型的IEnumerable返回头一个强类型的元素  
        /// </summary>  
        [DebuggerStepThrough]
        public static T First<T>(this IEnumerable col)
        {
            return (T)col.First();
        }

        /// <summary>
        /// 基本上和List<T>的ForEach方法一致。 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="col"></param>
        /// <param name="handler"></param>
        [DebuggerStepThrough]
        public static void Each<T>(this IEnumerable<T> col, Action<T> handler)
        {
            foreach (var item in col)
                handler(item);
        }

        /// <summary>  
        /// 带索引的遍历方法。
        /// </summary> 
        [DebuggerStepThrough]
        public static void Each<T>(this IEnumerable<T> col, Action<T, int> handler)
        {
            int index = 0;
            foreach (var item in col)
                handler(item, index++);
        }

        /// <summary> 
        /// 可以半途中断执行的遍历方法。 
        /// </summary> 
        [DebuggerStepThrough]
        public static void Each<T>(this IEnumerable<T> col, Func<T, bool> handler)
        {
            foreach (var item in col)
            {
                if (!handler(item)) break;
            }
        }

        /// <summary>  
        /// 可以半途中段的带索引的遍历方法。  
        /// </summary>  
        [DebuggerStepThrough]
        public static void Each<T>(this IEnumerable<T> col, Func<T, int, bool> handler)
        {
            int index = 0;
            foreach (var item in col)
                if (!handler(item, index++)) break;
        }
        #endregion

        #region 以下为IEnumerable<T>的非泛型实现
        [DebuggerStepThrough]
        public static void Each<T>(this IEnumerable col, Action<object> handler)
        {
            foreach (var item in col)
                handler(item);
        }
        [DebuggerStepThrough]
        public static void Each<T>(this IEnumerable col, Action<object, int> handler)
        {
            int index = 0;
            foreach (var item in col)
                handler(item, index++);
        }
        [DebuggerStepThrough]
        public static void Each<T>(this IEnumerable col, Func<object, bool> handler)
        {
            foreach (var item in col)
                if (!handler(item)) break;
        }
        [DebuggerStepThrough]
        public static void Each<T>(this IEnumerable col, Func<object, int, bool> handler)
        {
            int index = 0;
            foreach (var item in col)
                if (!handler(item, index++)) break;
        }

        #endregion
    }


    public class ObjectProperty
    {
        /// <summary> 属性信息
        /// </summary>
        public PropertyInfo Info { get; set; }
        /// <summary> Set方法委托
        /// </summary>
        public PropertySetter Setter { get; set; }
        /// <summary>
        /// 基础类型
        /// </summary>
        public Type BaseType { get; set; }
        //缓存
        static readonly Dictionary<Type, ObjectProperty[]> Cache = new Dictionary<Type, ObjectProperty[]>();
        public delegate void PropertySetter(object instance, object value);

        /// <summary> 获取一个类中的所有公开实例属性和它们的Set方法委托
        /// </summary>
        public static ObjectProperty[] GetProperties(Type type)
        {
            ObjectProperty[] arr;
            if (Cache.TryGetValue(type, out arr))//优先从缓存中获取
            {
                return arr;
            }
            PropertyInfo[] ps = type.GetProperties();
            arr = new ObjectProperty[ps.Length];
            for (int i = 0; i < ps.Length; i++)
            {
                ObjectProperty op = new ObjectProperty();
                op.Info = ps[i];
                op.Setter = CreateSetter(op.Info);  //之前定义的方法
                op.BaseType = op.Info.PropertyType.IsGenericType && op.Info.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)) ? op.Info.PropertyType : op.Info.PropertyType.GetGenericArguments()[0];
                arr[i] = op;
            }
            Cache.Add(type, arr); //加入缓存
            return arr;
        }
        /// <summary> 创建指定属性的Set方法委托
        /// </summary>
        public static PropertySetter CreateSetter(PropertyInfo property)
        {
            var type = property.DeclaringType;
            var dm = new DynamicMethod("", null, new[] { typeof(object), typeof(object) }, type);
            //=== IL ===
            var il = dm.GetILGenerator();
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_1);
            if (property.PropertyType.IsValueType)//判断属性类型是否是值类型
            {
                il.Emit(OpCodes.Unbox, property.PropertyType);//如果是值类型就拆箱
            }
            else
            {
                il.Emit(OpCodes.Castclass, property.PropertyType);//否则强转
            }
            il.Emit(OpCodes.Callvirt, property.GetSetMethod());
            il.Emit(OpCodes.Ret);
            //=== IL ===
            return (PropertySetter)dm.CreateDelegate(typeof(PropertySetter));
        }
    }

}
